using System.Collections.Generic;
using UnityEngine;

namespace GameToolkit
{
    [DisallowMultipleComponent, RequireComponent(typeof(Renderer)), ExecuteAlways]
    public sealed class OverrideMPB : MaterialOverrider
    {
        BlockInst mBlock;
        bool mIsInitialized;
        bool TryInitialize() 
        {
            if (mIsInitialized)
                return mIsInitialized;
            if (mBlock == null)
            {
                mBlock = new BlockInst(GetInstanceID());
                mBlock.Retain();
            }
            if(AttachedRenderer != null)
            {
                mBlock.material = AttachedRenderer.sharedMaterial;
                mIsInitialized = true;
            }
            return mIsInitialized;
        }

        protected override void OnDestroy()
        {
            base.OnDestroy();
            mIsInitialized = false;
            if(mBlock != null)
            {
                mBlock.Release();
                mBlock = null;
            }
        }

        protected override void OnFeatureEnabled()
        {
            TryInitialize();
            //mRenderer.SetPropertyBlock()
            //Debug.LogFormat(gameObject, "Activite MPB: {0}", name);
        }

        protected override void OnFeatureDisabled()
        {
            AttachedRenderer.SetPropertyBlock(null);
            //Debug.LogFormat(gameObject, "Inactivite MPB: {0}", name);
        }

        internal override void ResetMaterialCbuffer()
        {
            if (mIsInitialized)
                mBlock.Clear();
        }

        internal override void SetupMaterialCbuffer(ICbufferBlock cbuffer, HashSet<int> idCache)
        {
            if (mIsInitialized)
            {
                var r = AttachedRenderer;
                cbuffer.OnSetupMaterial(r, -1, mBlock);
            }
            //r.SetPropertyBlock(mBlock.block);
        }

        internal override void SubmitMaterialCbuffers()
        {
            if (mIsInitialized)
            {
                AttachedRenderer.SetPropertyBlock(mBlock.block);
            }
        }

        internal class BlockInst : MaterialGroupOverrider.Inst
        {
            internal readonly static BlockInst sharingInst = new BlockInst();
            internal MaterialPropertyBlock block;
            internal Material material;
            private BlockInst() : base(0) { }
            internal BlockInst(int id) : base(id)
            {
                this.block = new MaterialPropertyBlock();
            }
            protected override void OnRelease()
            {
                block.Clear();
                block = null;
            }

            public override void EnableKeyword(string keyword)
            {
                if (material != null)
                    material.EnableKeyword(keyword);
                //else
                //    Shader.EnableKeyword(keyword);
            }

            public override void DisableKeyword(string keyword)
            {
                if (material != null)
                    material.DisableKeyword(keyword);
                //else
                //    Shader.DisableKeyword(keyword);
            }

            public override void Clear()
            {
                block.Clear();
            }
            public override void SetColor(int id, Color color)
            {
                block.SetColor(id, color);
            }

            public override void SetInt(int id, int value)
            {
                block.SetInt(id, value);
            }

            public override void SetFloat(int id, float value)
            {
                block.SetFloat(id, value);
            }

            public override void SetTexture(int id, Texture tex)
            {
                block.SetTexture(id, tex);
            }

            public override void SetVector(int id, Vector4 vector)
            {
                block.SetVector(id, vector);
            }
        }
    }
}
